#ifndef  __COMBAT_DATA_HH__IMP__
#define  __COMBAT_DATA_HH__IMP__


#include "CombatSysIf.h"
#include "CombatDefinition.h"
#include "CombatSkill.h"
#include "Combat/States/CombatState.h"
#include "Combat/EvtCombat.h"
#include "Data/Flags.h"


class IEntity;
class CombatSkill;


#define		COMBAT_ONE_BOTTLE_HP_VALUE		100
#define		COMBAT_ONE_BOTTLE_ENERGY_VALUE	100

/*
*
*	Combat System Implementation
*	Spell caster basis, it provide the ability to cast a spell with a progress.
*	the spell caster also act as a manager of combat state for its host unit, so most combat state transition 
*	happened in this class.
*	
*
*/
class TCOM_API  CombatSysImp : public ICombatSys
{
public:
	CombatSysImp();
	virtual ~CombatSysImp();

	//
	//	Entity Combat Flags : pay attention to all combat flag index
	virtual	void setFlg(const short& idx);
	virtual	void clrFlg(const short& idx);
	virtual	bool hasFlg(const short& idx)const;

	//
	//	Entity Combat State
	//
	virtual	void		setState(short);
	virtual	short		getState()const;
	virtual	const char*	getStateName()const;
	virtual	const char* getStateName(short st)const;

	//
	//	Entity Factions
	virtual	void		setFaction(short f);
	virtual	short		getFaction()const;
	virtual	const char*	getFactionName()const;

	//
	//	set gene host
	//
	virtual bool setHost(IGeneHost* pHost);

	//
	//	Entity Extension Data for combat
	//	For setExtData nValue is the value to set
	//	For getExtData nValue is the default value , when failed to get specific data
	//
	virtual void	setExtData(short nIdx, const int& nValue = 0);
	virtual int		getExtData(short nIdx, const int& nValue = 0);

	//
	//	
	//
	virtual	void		setHP(int val);
	virtual	void		setMaxHP(int val);
	virtual	void		setMP(int val);
	virtual void		setMaxMP(int val);
	virtual	int			getHP()const;
	virtual	int			getMaxHP()const;
	virtual	int			getMP()const;
	virtual	int			getMaxMP()const;
	virtual	int			getHPPercentage()const;
	virtual	int			getMPPercentage()const;

	virtual	int			getBottleHP()const;
	virtual	int			getBottleMP()const;
	virtual	int			getHpBottleNum() const;
	virtual	int			getMpBottleNum() const;


	//
	//	Entity Combat Data update
	//
	virtual	void	updateHPByPercentage(int nPercent);
	virtual	void	updateHP(int nAffectValue);
	virtual	void	updateMP(int nAffectValue);
	virtual	void	updateMaxHP(int nAffectValue);
	virtual	void	updateHPBottleValue(int nAffectValue) ;
	virtual	void    updateMPBottleValue(int nAffectValue) ;

	//
	//	Entity base props
	//	vit, str, agi, int, 
	//	tohit, tododge,  
	//	critical, resist
	//	ap, dp
	//
	virtual void	setProps(short nIdx, const int& nValue = 0);
	virtual int		getProps(short nIdx) const;
	virtual void	setPropsModifier(short nIdx, const int& nValue = 0);
	virtual int		getPropsModifier(short nIdx) const;

	//
	//	Entity Immunity
	bool	addImmunity(int nKey);
	bool	rmvImmunity(int nKey);
	bool	hasImmunity(int nKey)const;
public:
	//	
	//	Gene ID
	//
	virtual int		getID()const;	

	//
	//	Mutex Rule
	//
	virtual int		getMutexRule()const;	

	//
	//	Mutex Group
	//
	virtual int		getMutexGroup()const;

	//
	//	Time To Live (Duration)
	//
	virtual int		getDuration()const;	
	//
	//	Static Gene Data
	virtual IData*	getStaticData();

	//
	//	Gene functions
	//
	virtual bool onInit(IGeneCreateData& createData);
	// 
	//	Fire when the gene is attached on a unit. just like unit enter the state.
	//
	virtual bool onAttach();

	// 
	//	Fire when the gene is attached on a unit. just like unit enter the state.
	//
	virtual bool onDetach();

	// 
	//	Periodically update gene logic, normally a gene will be detach when run out of its time to live.
	//
	virtual bool onUpdate(const int& nElapse);

	// 
	//	onEvent callback from hook manager
	//
	virtual void onEvent(IEvt& evt);

	//
	//	onEvent event handlers
	//
	virtual void onEvent_CastPrep(IEvt& evt);
	virtual void onEvent_Cast(IEvt& evt);
	virtual void onEvent_Target(IEvt& evt);
	virtual void onEvent_CastResult(IEvt& evt);

	//
	//	Calculator or Demonstrator
	virtual	bool isCalculator()const = 0;

	bool	hasSkill(short& nStyle)const;
	bool	hasSequence(const short& nSeq)const;

	//
	//	UI Effects
	//
	bool	EffectUpdate_CastStart(int& nTTL);		//	response on server's cast start notification
	bool	EffectUpdate_CastCancel();				//	cast is cancelled, maybe send a cancel message to server
	bool	EffectUpdate_CastEnding();				//	An logic step, calculator will send cast end request to server
	bool	EffectUpdate_CastEnded();				//	response on server's cast end notification
	//
	//	Target of current casting
	IEntity*	getTarget(const int& nTargetID ); 
	IEntity*	getTargetCC();
	//
	//	Target of current enemy
	void				setTargetCE(int nUIID){	m_nTargetCE = nUIID;	}
	IEntity*			getTargetCE();
	int					getTargetCE_ID()const			{	return m_nTargetCE;	}
	bool				hasTargetCE()const				{	return (m_nTargetCE!=0);	}

	//
	//	Spell to cast
	virtual bool TryCastNewSpell() = 0;

	//
	//	Send Combat Messages
	bool sendMsg_CbtTargt(IEntity& t);
	bool sendMsg_CbtStart(IEntity& t, CombatSkill& ab);
	bool sendMsg_CbtEnd();
	bool sendMsg_CbtCancel();

	//
	//	Combat calculate
	//	c casting ab on t, result in r
	static void calculate(ICombatCalculator* pCalculator);
	static bool calculate(CombatSkill& ab, IEntity& c, IEntity& t, CombatResult& r, ICombatCalculator* pOverrideCalculator = NULL);
#ifdef _DEBUG
	//
	//	Debug Helper Function
	virtual	const char*		getCombatTag()const = 0;

	short		MoR;
#endif

protected:
	static ICombatCalculator*	s_pCurDefaultCalculator;

	short	m_theCbtSt;
	short	m_nFaction;

	woe::Flags<32>	m_flags;
	bool	m_bInited;	//	identify whether current combat data has been initialized

protected:
	int	sMaxHP;
	int	sMaxMP;
	int	sHP;
	int	sMP;
	int	sHPBottleValue;
	int	sMPBottleValue;

	int	m_nProps[prop_max];
	int	m_nPropsModifier[prop_max];

	typedef	std::map<int, short>	ImmunityMap;

	ImmunityMap	m_theImmunityMap;

protected:
	bool		initState(short nST, ICombatState* pState);

	IEntity*	m_wpHost;

	//
	//	all data for current casting spell
	//
	CombatSkill*	m_wpCastingSkill;
	int	m_nTargetCC;
	short			m_nSequenceCC;

	//
	//	target of current enemy
	int	m_nTargetCE;

	//
	//	3D Animation, Effect and Sound
	//
	int m_nSR_SpellcastingBaseForCls;
	int m_nSR_SpellcastedBaseForCls;
	int	m_nSR_SpellcastingBaseForElement;
	int m_nSR_SpellcastingBaseForUnderAttack;

	short m_nPrevCbtSt;			//	previous combat state, try to keep sync with combat state in combat data
	//	check this state to see if someone change the combat state from other gene

	short m_nTimeLine;

	ICombatState*	m_theStates[Combat::CBS_End];
	short m_nSequenceGen;
};

#endif
